package com.coincalf.wallet.service.impl;

import com.baomidou.mybatisplus.mapper.EntityWrapper;
import com.coincalf.feign.CoinServiceClient;
import com.coincalf.wallet.entity.AddressPool;
import com.coincalf.wallet.entity.UserAddress;
import com.coincalf.wallet.entity.UserMemo;
import com.coincalf.wallet.mapper.UserAddressMapper;
import com.coincalf.wallet.service.AddressPoolService;
import com.coincalf.wallet.service.UserAddressService;
import com.baomidou.mybatisplus.service.impl.ServiceImpl;
import com.coincalf.wallet.service.UserMemoService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.HashMap;
import java.util.List;
import java.util.Map;

/**
 * <p>
 * 用户钱包地址信息 服务实现类
 * </p>
 *
 * @author crow
 * @since 2018-05-16
 */
@Slf4j
@Service
public class UserAddressServiceImpl extends ServiceImpl<UserAddressMapper, UserAddress> implements UserAddressService {

    @Autowired
    private AddressPoolService addressPoolService;
    @Autowired
    private UserMemoService userMemoService;
    @Autowired
    private CoinServiceClient coinServiceClient;

    /**
     * 查询用户钱包地址
     *
     * @param userId 用户ID
     * @param coinId 币种ID
     * @return
     */
    @Override
    public UserAddress queryByUserAndCoin(Long userId, Long coinId) {
        EntityWrapper<UserAddress> addressWrapper = new EntityWrapper<>();
        addressWrapper.eq("user_id", userId)
                .eq("coin_id", coinId);
        return super.selectOne(addressWrapper);
    }

    /**
     * 获取充币地址
     *
     * @param userId     用户ID
     * @param coinId     币种ID
     * @param mainCoinId 主链币种ID
     * @return
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public Map<String, String> getAddress(Long userId, Long coinId, Long mainCoinId) {
        //XRP以及EOS特殊处理 充币地址为平台地址但是memo不一样 分别为userId
        Map<String, String> response = new HashMap<>(2);
        // TODO: 2020/12/28 XRP  EOS coinId从数据库币种配置表coin获取 这里是写死的
        if (coinId == 8 || coinId == 9) {
            UserMemo userMemo = userMemoService.selectOneByUserId(userId);
            if (coinId == 8) {
                //XRP
                response.put("memo", String.valueOf(userMemo.getTag()));
            } else {
                //EOS
                response.put("memo", String.valueOf(userMemo.getMemo()));
            }
            AddressPool addressPool = addressPoolService.selectAddress(coinId);
            if (addressPool == null) {
                log.warn("数据库ex_wallet-address_pool表暂未配置该币种信息 coinId={}", coinId);
                response.put("address", "暂不支持该币种充币");
            } else {
                response.put("address", addressPool.getAddress());
            }
            return response;
        }

        //其他币种充币地址获取
        Long mcId = coinServiceClient.selectMainCoinIdByCoinId(coinId);
        if (mcId != null) {
            UserAddress userAddress = this.queryByUserAndCoin(userId, mcId);
            if (userAddress != null) {
                response.put("address", userAddress.getAddress());
                return response;
            }
            // 未获取主链钱包地址，则通过主链币种ID获取钱包地址
            AddressPool addressPool = addressPoolService.selectAddress(mcId);
            if (addressPool != null) {
                // 添加用户当前token币种钱包地址，与主链地址保持一致
                userAddress = new UserAddress(userId, mcId, addressPool.getAddress(), addressPool.getKeystore(), addressPool.getPwd(), addressPool.getPrivateKey());
                baseMapper.insert(userAddress);
                addressPoolService.deleteById(addressPool.getId());
                response.put("address", addressPool.getAddress());
                return response;
            } else {
                log.info("地址池地址已消耗完毕 请及时添加 conId={}", coinId);
                return response;
            }
        } else {
            log.warn("获取充币地址失败 userId={} coinId={}", userId, coinId);
            return null;
        }
    }

    @Override
    public List<UserAddress> selectListByCoinId(Long coinId) {
        EntityWrapper<UserAddress> wrap = new EntityWrapper<>();
        wrap.eq("coin_id", coinId);
        return super.selectList(wrap);
    }

    @Override
    public boolean selectExist(String address) {
        EntityWrapper<UserAddress> wrap = new EntityWrapper<>();
        wrap.eq("address", address);
        return super.selectCount(wrap) > 0;
    }

}
